﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

using zijian666.Converts;
using zijian666.Converts.Core;
using zijian666.Converts.Json;

namespace XUnitTest;

public class JsonTest4
{
    public JsonTest4()
    {
        if (!Debugger.IsAttached)
        {
        }
        _ = DiagnosticListener.AllListeners.Subscribe(new DiagnosticObserver());
    }

    [Fact]
    public void FormatterConverter()
    {
        var converter = Converts.GetFormatterConverter();
        var result = converter.ToInt32("123");
        Assert.Equal(123, result);
    }

    [Fact]
    public void JsonConvertor()
    {
        Converts.Settings.Protocol = "json";
        Converts.SetStringSerializer(new JsonStringSerializer());

        {
            var data = new
            {
                id = 1,
                name = "zijian666",
            };
            var json = data.To<string>();
            Console.WriteLine(json);
            Assert.Equal(JsonConvert.SerializeObject(data), json);

            var result = json.Convert(data.GetType());
            Assert.True(result.Success);
            dynamic data2 = result.Value;
            Assert.True(data.id == (int)data2.id);
            Assert.True(data.name == (string)data2.name);
        }

        {
            var data = new[]
            {
                new {id = 1, name = "zijian666"},
                new {id = 2, name = "blqw"}
            };
            var json = data.To<string>();
            Console.WriteLine(json);
            Assert.Equal(JsonConvert.SerializeObject(data), json);

            var result = json.Convert(data.GetType());
            Assert.True(result.Success);
            dynamic data2 = result.Value;
            Assert.Equal(data[0].id, data2[0].id);
            Assert.Equal(data[0].name, data2[0].name);
            Assert.Equal(data[1].id, data2[1].id);
            Assert.Equal(data[1].name, data2[1].name);
        }

        {
            var data = new Dictionary<string, dynamic>
            {
                ["1"] = new { id = 1, name = "zijian666" },
                ["2"] = new { id = 2, name = "blqw" }
            };
            var json = data.To<string>();
            Console.WriteLine(json);
            Assert.Equal(JsonConvert.SerializeObject(data), json);

            var type = typeof(Dictionary<,>).MakeGenericType(typeof(string), ((object)data["1"]).GetType());
            var result = json.Convert(type);
            Assert.True(result.Success);
            dynamic data2 = result.Value;
            Assert.Equal(data["1"].id, data2["1"].id);
            Assert.Equal(data["1"].name, data2["1"].name);
            Assert.Equal(data["2"].id, data2["2"].id);
            Assert.Equal(data["2"].name, data2["2"].name);
        }

        {
            var data = new List<dynamic>
            {
                new {id = 1, name = "zijian666"},
                new {id = 2, name = "blqw"}
            };
            var json = data.To<string>();
            Console.WriteLine(json);
            Assert.Equal(JsonConvert.SerializeObject(data), json);

            var type = typeof(List<>).MakeGenericType(((object)data[0]).GetType());
            var result = json.Convert(type);
            Assert.True(result.Success);
            dynamic data2 = result.Value;
            Assert.Equal(data[0].id, data2[0].id);
            Assert.Equal(data[0].name, data2[0].name);
            Assert.Equal(data[1].id, data2[1].id);
            Assert.Equal(data[1].name, data2[1].name);
        }

        {
            var data = new Dictionary<string, dynamic>
            {
                ["1"] = new { id = 1, name = "zijian666" },
                ["2"] = new { id = 2, name = "blqw" }
            };
            var json = data.To<string>();
            Console.WriteLine(json);
            Assert.Equal(JsonConvert.SerializeObject(data), json);

            var result = json.Convert<NameValueCollection>();
            Assert.True(result.Success);
            var data2 = result.Value;

            Assert.Equal(JsonConvert.SerializeObject(data["1"]), data2["1"]);
            Assert.Equal(JsonConvert.SerializeObject(data["2"]), data2["2"]);
        }
    }

    [Fact]
    public void JsonToDatetimeBug()
    {
        Converts.Settings.Protocol = "json";
        Converts.SetStringSerializer(new JsonStringSerializer());

        {
            var data = new
            {
                time = DateTime.Parse("2020-10-06 01:07:27")
            };

            var json = data.To<string>();
            Console.WriteLine(json);
            Assert.Equal("{\"time\":\"2020-10-06 01:07:27\"}", json);
        }

        {
            var data = new
            {
                time = DateTime.Parse("2020-10-06 01:07:27")
            };

            var json = data.Convert<string>(new ConvertSettings().SetToStringArgument(typeof(DateTime), "yyyy年MM月dd日")).Value;
            Console.WriteLine(json);
            Assert.Equal("{\"time\":\"2020年10月06日\"}", json);
        }
    }

    [Fact]
    public void JsonBug20201006()
    {
        var json = "{\"ID\":1,\"NUMBER\":1,\"NAME\":\"\u4EFB\u660A\u777F\",\"PHONE_BA\":\"13588890280\",\"PHONE_MA\":\"13588828151\",\"GENDER\":\"\u7537\",\"IDENTITY_CARD\":\"33010420121008271X\",\"ADDRESS\":\"\",\"LEAVED\":0,\"CREATED_AT\":\"2019-09-22 05:19:20\",\"MODIFIED_AT\":\"2019-09-22 05:19:20\",\"PHONE\":\"\"}";

        var x = json.To<Students>();
        Console.WriteLine($"{x}");

        var y = x.To("");
        Assert.Equal(json, y);
    }

    [Fact]
    public void JsonStringSerializerTest()
    {
        JsonStringSerializer serializer = new JsonStringSerializer();
        var g = Guid.NewGuid();
        var x = serializer.ToString(new Guid[] { g });
        Console.WriteLine(x);
        Assert.Equal("[\"" + g.ToString() + "\"]", x);
    }

    [Fact]
    public void JsonStringSerializerToObjectTest()
    {
        JsonStringSerializer serializer = new JsonStringSerializer();
        var arr = new[] { 1, 2, 3, 4, 5 };
        var json1 = JsonConvert.SerializeObject(arr);
        dynamic arr1 = serializer.ToObject(json1);
        Assert.Equal(arr.Length, arr1.Length);
        for (int i = 0; i < arr.Length; i++)
        {
            Assert.True(arr[i] == (int)arr1[i]);
        }
        var dict = new { id = 1, name = "zijian666" };
        var json2 = JsonConvert.SerializeObject(dict);
        dynamic dict1 = serializer.ToObject(json2);
        Assert.True(dict.id == (int)dict1.id);
        Assert.True(dict.name == (string)dict1.name);
    }

    [Fact]
    public void JsonStringSerializerToObject2Test()
    {

        {
            var data = 1m;
            JsonStringSerializer serializer = new JsonStringSerializer();
            var json = serializer.ToString(data);
            var obj = serializer.ToObject(json);
            var x = serializer.ToString(obj);
            Assert.Equal(json, serializer.ToString(obj));
        }

        {
            var data = new { id = 1m, name = "zijian666" };
            JsonStringSerializer serializer = new JsonStringSerializer();
            var json = serializer.ToString(data);
            var obj = serializer.ToObject(json);
            var x = serializer.ToString(obj);
            Assert.Equal(json, serializer.ToString(obj));
        }


        {
            var data = new Dictionary<string, dynamic>
            {
                ["1"] = new { id = 1m, name = "zijian666" },
                ["2"] = new { id = 2, name = "blqw" }
            };
            JsonStringSerializer serializer = new JsonStringSerializer();


            var json = serializer.ToString(data);
            var obj = serializer.ToObject(json);
            var x = serializer.ToString(obj);
            Assert.Equal(json, serializer.ToString(obj));
        }

    }

    public class Students
    {
        public int ID { get; set; }
        public int NUMBER { get; set; }
        public string NAME { get; set; }
        public string PHONE_BA { get; set; }
        public string PHONE_MA { get; set; }
        public string GENDER { get; set; }
        public string IDENTITY_CARD { get; set; }
        public string ADDRESS { get; set; }
        public int LEAVED { get; set; }
        public DateTime CREATED_AT { get; set; }
        public DateTime MODIFIED_AT { get; set; }
        public string PHONE { get; set; }
    }



#if NET45_OR_GREATER
    [Fact]
    public void 测试动态类型转JSON()
    {
        var json = "{\"id\":1,\"name\":\"zijian666\",\"enabled\":true}";
        var dy = json.To<Dictionary<string, dynamic>>();
        var options = new JsonSerializerSettings
        {
            Converters = {
                    JsonConverters.ProxyObject,
                    JsonConverters.Guid,
                    JsonConverters.DateTime,
                    JsonConverters.DateTimeOffset,
                    JsonConverters.TimeSpan,
                    JsonConverters.JToken,
                }
        };
        var json3 = JsonConvert.SerializeObject(dy, options);

        Assert.Equal(json, json3);
        var jobj = JToken.Parse(json3);
        var json2 = JsonConvert.SerializeObject(jobj, options);
        Assert.Equal(json, json2);

        var user = json.To<User>();
        Assert.Equal(1, user.Id);
        Assert.Equal("zijian666", user.Name);
        Assert.Equal(true, user.Enabled);
        var json4 = JsonConvert.SerializeObject(user, options);
    }
#endif
}
